#include "i2c.h"

void delay_us(uint8_t time)
{
    for (uint8_t i = 0; i < time; i++) {
        for (uint8_t j = 0; j < 72; j++) {
            __NOP();
        }
    }
}
void i2c_init(void)
{
    __HAL_RCC_GPIOB_CLK_ENABLE();

    GPIO_InitTypeDef GPIO_InitStructure = {0};
    GPIO_InitStructure.Pin              = SCL | SDA;
    GPIO_InitStructure.Mode             = GPIO_MODE_OUTPUT_OD;
    GPIO_InitStructure.Pull             = GPIO_PULLUP;
    GPIO_InitStructure.Speed            = GPIO_SPEED_FREQ_HIGH;
    HAL_GPIO_Init(I2C_PORT, &GPIO_InitStructure);
}

void SDA_H()
{
    HAL_GPIO_WritePin(I2C_PORT, SDA, GPIO_PIN_SET);
    delay_us(DELAY_TIME);
}

void SDA_L()
{
    HAL_GPIO_WritePin(I2C_PORT, SDA, GPIO_PIN_RESET);
    delay_us(DELAY_TIME);
}

void SCL_H()
{
    HAL_GPIO_WritePin(I2C_PORT, SCL, GPIO_PIN_SET);
    delay_us(DELAY_TIME);
}

void SCL_L()
{
    HAL_GPIO_WritePin(I2C_PORT, SCL, GPIO_PIN_RESET);
    delay_us(DELAY_TIME);
}
int SDA_Read()
{
    return HAL_GPIO_ReadPin(I2C_PORT, SDA);
}
void start()
{
    i2c_init();
    SDA_H();
    SCL_H();
    SDA_L();
    SCL_L();
}

void stop()
{
    SDA_L();
    SCL_L();
    SCL_H();
    SDA_H();
}

void sendbyte(uint8_t byte)
{
    SCL_L();
    for (uint8_t i = 0; i < 8; i++) {
        if (byte & 0x80) {
            SDA_H();
        } else {
            SDA_L();
        }
        SCL_H();
        SCL_L();
        byte <<= 1;
    }
    SCL_H();
    // 处理应答
    SCL_L();
}

uint8_t readbyte()
{
    uint8_t byte = 0;
    SCL_H();
    for (uint8_t i = 0; i < 8; i++) {
        byte <<= 1;
        if (SDA_Read()) {
            byte |= 0x01;
        }
        SCL_L();
        SCL_H();
    }
    return byte;
}

void ack() // 应答
{
    SCL_L();
    SDA_L();
    SCL_H();
    SCL_L();
}
void nack() // 非应答
{
    SCL_L();
    SDA_H();
    SCL_H();
    SCL_L();
}
void senddata(uint8_t address, uint8_t *data, uint8_t len)
{
    start();
    address <<= 1;
    sendbyte(address);

    for (uint8_t i = 0; i < len; i++) {
        sendbyte(data[i]);
        // 检测应答信号
    }
    stop();
}

void readdata(uint8_t address, uint8_t *data, uint8_t len)
{
    start();

    sendbyte((address << 1) | 0X01);
    for (uint8_t i = 0; i < len; i++) {
        data[i] = readbyte();
        if (i == len) {
            nack();
        } else {
            ack();
        }
    }
    stop();
}